# encoding: utf-8
# @File  : lifecycle.py
# @Author: shaoyun
# @Date  :  2025/05/30
"""
应用生命周期管理
处理应用启动、关闭、后台任务等
"""
import asyncio
from contextlib import asynccontextmanager
from typing import List

from fastapi import FastAPI
from loguru import logger

from app.core.config import settings
from app.db.mongo_manager import MongoDB
from app.db.redis_manager import RedisClient


@asynccontextmanager
async def lifespan(app: FastAPI):
    """
    使用 lifespan 上下文管理器管理应用生命周期
    确保所有初始化都在同一个事件循环中完成
    """
    # 启动时执行
    logger.info("Starting up application...")

    # 初始化数据库连接
    await init_databases()

    # 启动后台任务
    background_tasks = await start_background_tasks()

    yield

    # 关闭时执行
    logger.info("Shutting down application...")

    # 停止后台任务
    await stop_background_tasks(background_tasks)

    # 关闭数据库连接
    await close_databases()


async def init_databases():
    """初始化数据库连接"""
    # 连接到MongoDB
    await MongoDB.connect_async()
    MongoDB.connect_sync()
    logger.info("Connected to MongoDB")

    # 确保Redis连接正常
    try:
        client = await RedisClient.get_client()  # 使用异步方法
        await client.ping()  # 异步 ping
        logger.info("Connected to Redis")
    except Exception as e:
        logger.error(f"Failed to connect to Redis: {e}")
        raise


async def close_databases():
    """关闭数据库连接"""
    # 关闭MongoDB连接
    await MongoDB.close_async()
    MongoDB.close_sync()
    logger.info("Closed MongoDB connection")

    # 关闭Redis连接
    await RedisClient.close()
    logger.info("Closed Redis connection")


async def start_background_tasks() -> List[asyncio.Task]:
    """启动所有后台任务"""
    background_tasks = []

    # 启动任务调度器
    from app.services.task_scheduler import TaskScheduler
    logger.info("Starting task scheduler...")
    scheduler_task = asyncio.create_task(TaskScheduler.run_scheduler_loop())
    background_tasks.append(scheduler_task)

    # 启动节点健康检查
    from app.services.node_manager import NodeManager
    logger.info("Starting node health check...")
    health_check_task = asyncio.create_task(NodeManager.run_health_check_loop())
    background_tasks.append(health_check_task)

    # 启动监控服务
    from app.services.monitor import Monitor
    logger.info("Starting monitoring service...")
    monitor_task = asyncio.create_task(Monitor.run_monitoring_loop())
    background_tasks.append(monitor_task)

    # 启动定时任务处理器（如果启用）
    if settings.ENABLE_CRON_PROCESSOR:
        from app.utils.cron_processor import CronProcessor
        logger.info("Starting cron processor...")
        cron_task = asyncio.create_task(CronProcessor.run_cron_loop())
        background_tasks.append(cron_task)

    return background_tasks


async def stop_background_tasks(tasks: List[asyncio.Task]):
    """停止所有后台任务"""
    logger.info("Cancelling background tasks...")

    # 取消所有后台任务
    for task in tasks:
        task.cancel()

    # 等待任务取消完成
    await asyncio.gather(*tasks, return_exceptions=True)

    logger.info("All background tasks cancelled")